xnregistry:内核对象注册与管理


xnregistry:全局对象注册表

在实时系统中,任务之间的同步与通信需要依赖各种内核对象,如信号量、互斥锁、消息队列等。为了支持进程间共享和快速检索,xkernel 提供了 xnregistry,用于统一管理和访问这些内核对象。

什么是 xnregistry?

xnregistryxkernel 内核的全局对象注册表,负责管理内核中的命名和未命名对象。它提供了一种机制,允许内核对象以唯一的标识符(如名称)注册,便于在内核和用户空间中查找和访问。

xnregistry 的作用

命名内核对象的管理

命名内核对象是指在创建时指定了名称的对象,通常用于多个进程之间的共享和通信。常见的命名内核对象包括:

创建和注册过程

以两个 xkernel 任务通过信号量进行同步为例:

任务 1 创建一个名为 /tmp/sem1 的信号量

/* 任务 1 */
sem_t *demo_sem;

demo_sem = sem_open("/tmp/sem1", O_CREAT | O_EXCL, 0666, 0);
if (demo_sem == SEM_FAILED)
    perror("sem_open");

sem_wait(demo_sem);
/* ... */
sem_post(demo_sem);

任务 2 打开同名信号量

/* 任务 2 */
sem_t *demo_sem;

demo_sem = sem_open("/tmp/sem1", 0);
if (demo_sem == SEM_FAILED)
    perror("sem_open");

sem_wait(demo_sem);
/* ... */
sem_post(demo_sem);

当任务 1 调用 sem_open 创建信号量时,内核会进行以下操作:

  1. 分配 xnobject 结构体:从 registry_obj_slots 中获取一个空闲的 xnobject,用于表示信号量对象。
  2. 设置 xnobject 的属性:
  3. 插入哈希表:

任务 2 想要打开同名信号量时,执行以下步骤:

  1. 计算名称的哈希值:对 /tmp/sem1 进行哈希计算,得到索引值 s。
  2. 在哈希表中查找: • 遍历 object_index[s] 链表,比较每个 xnobjectkey。 • 找到匹配的 xnobject 后,获取其 objaddr,即信号量对象的地址。

在成功创建或打开信号量后,系统会生成一个 xnhandle_t,表示对象的句柄。这个句柄通常是 xnobjectregistry_obj_slots 数组中的偏移量。任务在后续操作(如 sem_waitsem_post)中,使用这个句柄快速访问信号量对象,避免再次通过名称查找。

未命名内核对象的管理

未命名内核对象通常用于单个进程或线程内部,不需要跨进程共享。例如:

管理机制

未命名对象在创建时:

  1. 分配 xnobject:同样从 registry_obj_slots 中获取一个 xnobject
  2. 设置属性:
  1. 不插入哈希表:由于没有名称,匿名对象不需要插入到哈希表中。
  2. 生成句柄:返回 xnhandle_t,供后续操作使用。

访问方式

任务在后续对未命名对象的操作中,使用句柄 xnhandle_t 直接访问对象,而不需要通过名称查找。这种方式提高了访问速度,满足实时系统对性能的要求。

xnregistry 的初始化流程

初始化步骤

在系统启动时会初始化 xnregistry,具体步骤包括:

  1. 分配对象槽(registry_obj_slots):
  2. 初始化空闲链表(free_object_list):
  3. 创建哈希表(object_index):
  4. 初始化同步机制(register_synch):